package cas.ihep.spark.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class GlobalConfiguration {
    private GlobalConfiguration(){}
    private static final HashMap<String,String> props=new HashMap<>();
    private static final Method getNode;
    static{
        try{
            getNode=HashMap.class.getDeclaredMethod("getNode", int.class, Object.class);
            getNode.setAccessible(true);
        }catch (NoSuchMethodException ignored){
            throw new RuntimeException("Should never occurs");
        }
    }

    private static int hash(String key) {
        int h;
        return key == null ? 0 : (h = key.hashCode()) ^ h >>> 16;
    }

    public static String getProperty(String key){
        try {
            @SuppressWarnings("unchecked")
            Map.Entry<String,String> node=(Map.Entry<String,String>)getNode.invoke(props, hash(key), key);
            if(node!=null){
                return node.getValue();
            }
        }catch (IllegalAccessException | InvocationTargetException ignored){throw new RuntimeException("Should never happens");}
        return System.getProperty(key);
    }

    public static String getProperty(String key,String defVal){
        try {
            @SuppressWarnings("unchecked")
            Map.Entry<String,String> node=(Map.Entry<String,String>)getNode.invoke(props, hash(key), key);
            if(node!=null){
                return node.getValue();
            }
        }catch (IllegalAccessException | InvocationTargetException ignored){throw new RuntimeException("Should never happens");}
        return System.getProperty(key,defVal);
    }

    public static void update(Map<String,String> conf){
        for(Map.Entry<String,String> entry:conf.entrySet()){
            String key=entry.getKey();
            if(quickCheck(key,"spark.loop.log")){
                LogEnv.getInstance().setLogLevel(entry.getValue());
            }
            props.put(key,entry.getValue());
        }
    }

    public static Map<String,String> properties(){
        return props;
    }

    public static Map<String,String> propertiesWithSystem(){
        HashMap<String,String> ret= new HashMap<>();
        for(Map.Entry<Object,Object> e:System.getProperties().entrySet()){
            ret.put(e.getKey().toString(),e.getValue().toString());
        }
        ret.putAll(props);
        return ret;
    }

    public static void setProperty(String key,String value){
        if(quickCheck(key,"spark.loop.log")){
            LogEnv.getInstance().setLogLevel(value);
        }
        props.put(key,value);
    }

    @SuppressWarnings("SameParameterValue")
    private static boolean quickCheck(String s1, String s2){
        //noinspection RedundantCast
        if((Object)s1==(Object) s2){
            return true;
        }
        int len=s1.length();
        if(len!=s2.length()){
            return false;
        }
        for(int i=len-1;i>-1;i--){
            if(s1.charAt(i)!=s2.charAt(i)){
                return false;
            }
        }
        return true;
    }
}
